package com.xuecheng.media.service.impl;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.agent.ContentApiAgent;
import com.xuecheng.api.content.TeachplanMedia;
import com.xuecheng.api.content.model.CourseBaseDTO;
import com.xuecheng.api.media.model.MediaDTO;
import com.xuecheng.api.media.model.qo.QueryMediaModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.common.ResourceTypeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.media.common.constant.MediaErrorCode;
import com.xuecheng.media.common.utils.AliyunVODUtil;
import com.xuecheng.media.controller.MediaAudtoController;
import com.xuecheng.media.convert.MediaConvert;
import com.xuecheng.media.entity.Media;
import com.xuecheng.media.mapper.MediaMapper;
import com.xuecheng.media.service.MediaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 媒资信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class MediaServiceImpl extends ServiceImpl<MediaMapper, Media> implements MediaService {
   @Autowired
   private ContentApiAgent contentApiAgent;
    @Transactional
    public MediaDTO createMedia(MediaDTO dto) {
        //1.判断关键
        // companyid filename fileid(videoId)
        if (ObjectUtils.isEmpty(dto.getCompanyId())||
                StringUtil.isBlank(dto.getFilename())||
                StringUtil.isBlank(dto.getFileId())
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 2.给信息数据赋值默认值
        // auditStatus：未审核
        dto.setAuditStatus(AuditEnum.AUDIT_UNPAST_STATUS.getCode());
        // 3.保存信息
        Media media = MediaConvert.INSTANCE.dto2entity(dto);
        boolean result = this.save(media);
        if (!result) {
            ExceptionCast.cast(MediaErrorCode.E_140001);
        }
        // 4.将数据库最新数据返回
        Media po = this.getById(media.getId());
        MediaDTO resultDTO = MediaConvert.INSTANCE.entity2dto(po);
        return resultDTO;
    }

    /**
     * 1.是否要开启事务
     * 增删改需要开启事（不开启）
     * 参数判断（pageSize,pageno）没有参数给默认值
     * filename如果不为空，lamb添加like
     * type有就加上
     * 时间倒序
     * 是否删除
     * 机构id（只能查询自己机构的数据）
     * 返回用对象pageVo
     * @param params
     * @param model
     * @param companyId
     * @return
     */
    @Override
    public PageVO queryMediaList(PageRequestParams params, QueryMediaModel model, Long companyId) {
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }
        // filename如果不为空，lamb添加like
        //  type有就加上
        //  时间倒序
        //  是否删除
        //  机构id（只能查询自己机构的数据
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        if (!StringUtil.isEmpty(model.getFilename())){
            queryWrapper.like(Media::getFilename,model.getFilename());
        }
        if (!StringUtil.isEmpty(model.getAuditStatus())){
            queryWrapper.eq(Media::getAuditStatus,model.getAuditStatus());
        }
        if (!StringUtil.isEmpty(model.getType())){
            queryWrapper.eq(Media::getType,model.getType());
        }
        if (!ObjectUtils.isEmpty(companyId)){
            queryWrapper.eq(Media::getCompanyId,companyId);
        }
        queryWrapper.eq(Media::getStatus, CommonEnum.USING_FLAG.getCode());
        queryWrapper.orderByDesc(Media::getCreateDate);
        Page<Media> mediaPage = new Page<>(params.getPageNo(),params.getPageSize());
        Page<Media> vo = page(mediaPage, queryWrapper);
        List<Media> list = vo.getRecords();

        List<MediaDTO> dtoList  = Collections.emptyList();
        if (!ObjectUtils.isEmpty(list)){
           dtoList = MediaConvert.INSTANCE.entitys2dtos(list);
        }
        PageVO<MediaDTO> pageVO = new PageVO(dtoList,vo.getTotal(),params.getPageNo(),params.getPageSize());
        return pageVO;
    }

    @Override
    /**
     * 增删改需要开启事（开启）
     * 关键数据：
     * * 判断资源id是否为空
     * 业务数据：
     * * 判断使用态
     * * 不能删除已经发布的数据
     * * 判断状态（使用态不能删除）
     *  * 只能删除自己家的，
     *  未绑定课程的才可以删除
     */
    @Transactional
    public void removeMediaById(Long mediaId, Long companyId) {
        if (ObjectUtils.isEmpty(mediaId)){
            ExceptionCast.cast(MediaErrorCode.E_140007);
        }
        //查询该媒资是否绑定课程，绑定则不能删除
        //todo:远程
        RestResponse<TeachplanMedia> response = contentApiAgent.getTeachplanByMediaId(mediaId);
        if (!(response.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(response.getCode(),response.getMsg());
        }
        // 判断媒资信息是否存在
        TeachplanMedia teachplanMedia= response.getResult();
        if (!ObjectUtils.isEmpty(teachplanMedia)){
//                if (!ObjectUtils.isEmpty(teachplanMedia.getMediaId())){
//                    ExceptionCast.cast(MediaErrorCode.E_140010);
//                }
            ExceptionCast.cast(MediaErrorCode.E_140003);
        }

        //暂默认未绑定
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getCompanyId,companyId);
        queryWrapper.eq(Media::getId,mediaId);
        Media one = getOne(queryWrapper);
        if (ObjectUtils.isEmpty(one)){
            ExceptionCast.cast(MediaErrorCode.E_140008);
        }
        LambdaUpdateWrapper<Media> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Media::getId,one.getId());
        updateWrapper.set(Media::getStatus,CommonEnum.DELETE_FLAG.getCode());
        boolean update = update(updateWrapper);
        if (!update){
            ExceptionCast.cast(MediaErrorCode.E_140002);
        }

    }

    @Override
    /**
     * 审核
     *
   	媒资id 不能为空
   审核状态 不可为空
   审核意见  不可空应该
    业务数据：
   判断 媒资信息是否存在
   只能审核已提交的
   是否已经删除
     */
    @Transactional
    public void approve(MediaDTO dto) {
        if (ObjectUtils.isEmpty(dto.getId())||
                ObjectUtils.isEmpty(dto.getAuditMind())||
                ObjectUtils.isEmpty(dto.getAuditStatus())
        ){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        if (!(dto.getAuditStatus().equals("202002")||
        dto.getAuditStatus().equals("202001")||
        dto.getAuditStatus().equals("202003")
          )
        ){
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getId,dto.getId());
        queryWrapper.eq(Media::getAuditStatus,AuditEnum.AUDIT_UNPAST_STATUS.getCode());
        Media one = getOne(queryWrapper);
        if (ObjectUtils.isEmpty(one))
        {
            ExceptionCast.cast(MediaErrorCode.E_140008);
        }
        LambdaUpdateWrapper<Media> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Media::getId,dto.getId());
        updateWrapper.set(Media::getAuditMind,dto.getAuditMind());
        updateWrapper.set(Media::getAuditStatus,dto.getAuditStatus());
        boolean update = update(updateWrapper);
        if (!update) {
            ExceptionCast.cast(MediaErrorCode.E_140009);
        }
    }

    @Override
    public String getMediaUrl4b(Long mediaId) {
        if (ObjectUtils.isEmpty(mediaId)) {
            ExceptionCast.cast(MediaErrorCode.E_140007);
        }
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getId,mediaId);
        queryWrapper.eq(Media::getStatus,CommonEnum.USING_FLAG.getCode());
        //运营平台不判断公司id
        Media one = getOne(queryWrapper);
        if (ObjectUtils.isEmpty(one)) {
            ExceptionCast.cast(MediaErrorCode.E_140012);
        }
        if (ObjectUtils.isEmpty(one.getUrl())){
            ExceptionCast.cast(MediaErrorCode.E_140016);
        }
        return one.getUrl();
    }
@Override
    public String getPlayUrlByMediaId(Long mediaId, Long companyId) {

        // 1.判断关键数据
        if (ObjectUtils.isEmpty(mediaId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        // 2.判断业务数据
        // 媒资信息是否存在
        LambdaQueryWrapper<Media> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Media::getId, mediaId);

       if (!(ObjectUtils.nullSafeEquals(companyId, MediaAudtoController.OPERATION_FLAG))) {
            queryWrapper.eq(Media::getCompanyId, companyId);
        }

        Media media = this.getOne(queryWrapper);

        if (ObjectUtils.isEmpty(media)) {
            ExceptionCast.cast(MediaErrorCode.E_140005);
        }

        // 3.获得媒资文件的资源路径地址
        // 判断媒资类型是否是视频类型，如果是需要获得aliyun视频的地址
        String type = media.getType();


        String resourceUrl = null;

        if (ResourceTypeEnum.VIDEO. getCode().equals(type)) {
            resourceUrl = getAliyunVodPlayUrl(media.getFileId());
        } else if (ResourceTypeEnum.DOCUMENT.getCode().equals(type)){
            //获得的媒资文档的资源访问地址路径
        } else if (ResourceTypeEnum.WORK.getCode().equals(type)){
            //获得的媒资文档的资源访问地址路径
        }


        return resourceUrl;
    }


    @Value("${aliyun.region}")
    private  String region;
    @Value("${aliyun.accessKeyId}")
    private  String accessKeyId;
    @Value("${aliyun.accessKeySecret}")
    private  String accessKeySecret;


    /**
     * 获得阿里云视频播放地址
     * @param fileId
     * @return
     */
    private String getAliyunVodPlayUrl(String fileId) {

        String playURL = null;
        try {
            DefaultAcsClient client = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);

            GetPlayInfoResponse playInfo = AliyunVODUtil.getPlayInfo(client, fileId);

            List<GetPlayInfoResponse.PlayInfo> playInfoList = playInfo.getPlayInfoList();

            if (CollectionUtils.isEmpty(playInfoList)) {
                ExceptionCast.cast(MediaErrorCode.E_140018);
            }

            // 默认获得第一个播放地址
            playURL = playInfoList.get(0).getPlayURL();
        } catch (Exception e) {
            log.error(MediaErrorCode.E_140012.getDesc()+" : {}",e.getMessage());
            ExceptionCast.cast(MediaErrorCode.E_140012);
        }

        return playURL;
    }
}
